package pl.enigmatic.parser.xml;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import pl.enigmatic.parser.XMLAlias;
import pl.enigmatic.parser.XMLConverter;
import pl.enigmatic.parser.string.Converter;


public class PublicPropertyParser extends BasicPropertyParser<PublicPropertyParser.Setter> {

	protected static class Setter extends pl.enigmatic.parser.xml.BasicPropertyParser.Accessor {

		private static Parser<?> createParser(final Field f) {
			Converter<?> c = null;
			if (f.isAnnotationPresent(XMLConverter.class)) {
				c = Converter.create(f.getAnnotation(XMLConverter.class).value());
			}
			final Class<?> type = f.getType();
			return type != null ? Parser.createParser(type).copy(c) : null;
		}

		private final Field field;

		public Setter(final Field f) {
			super(f.getName(), f.getType(), createParser(f));
			field = f;
		}

		@Override
		public boolean access(final Object target, final Object value, final ParsingInfo<?> info) {
			try {
				field.set(target, value);
				return true;
			} catch (final Exception e) {
				return false;
			}
		}
	}

	public PublicPropertyParser(final Parser<?> parser) {
		super(parser, true);
		for (final Field f : owner.getClazz().getDeclaredFields()) {
			final int mod = f.getModifiers();
			if (!Modifier.isFinal(mod) && Modifier.isPublic(mod) && !Modifier.isStatic(mod)) {
				accessors.put(f.getName(), new Setter(f));
				if (f.isAnnotationPresent(XMLAlias.class)) {
					accessors.addAliases(f.getName(), f.getAnnotation(XMLAlias.class).value());
				}
			}
		}
	}

}
